package sm.hibernate.type;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.mina.core.buffer.IoBuffer;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
import org.hibernate.usertype.CompositeUserType;

import sm.codec.api.Codec;
import sm.codec.api.CodecFactory;
import sm.codec.exception.DecodeException;
import sm.codec.exception.EncodeException;
import sm.dbdict.def.DBDict;
import sm.util.Util;

public class DBDictType implements CompositeUserType {

	private Codec codec = CodecFactory.DBDICT_CODEC;

	private static final int MAX_SIZE = 65536;

	@Override
	public String[] getPropertyNames() {
		return new String[] { "name" };
	}

	@Override
	public Type[] getPropertyTypes() {
		return new Type[] { Hibernate.STRING };
	}

	@Override
	public Object getPropertyValue(Object component, int property)
			throws HibernateException {
		DBDict dbdict = (DBDict) component;
		return dbdict.getName();
	}

	@Override
	public void setPropertyValue(Object component, int property, Object value)
			throws HibernateException {
		DBDict dbdict = (DBDict) component;
		dbdict.setName((String) value);
	}

	@Override
	public Class returnedClass() {
		return DBDict.class;
	}

	@Override
	public boolean equals(Object x, Object y) throws HibernateException {
		return Util.equals(x, y);
	}

	@Override
	public int hashCode(Object x) throws HibernateException {
		return x == null ? 0 : x.hashCode();
	}

	@Override
	public Object deepCopy(Object value) throws HibernateException {
		DBDict dbdict = (DBDict) value;
		return dbdict.clone();
	}

	@Override
	public boolean isMutable() {
		return true;
	}

	@Override
	public Serializable disassemble(Object value, SessionImplementor session)
			throws HibernateException {
		return (Serializable) deepCopy(value);
	}

	@Override
	public Object assemble(Serializable cached, SessionImplementor session,
			Object owner) throws HibernateException {
		return deepCopy(cached);
	}

	@Override
	public Object replace(Object original, Object target,
			SessionImplementor session, Object owner) throws HibernateException {
		return deepCopy(original);
	}

	@Override
	public Object nullSafeGet(ResultSet rs, String[] names,
			SessionImplementor session, Object owner)
			throws HibernateException, SQLException {
		DBDict dbdict = null;
		byte[] bytes = (byte[]) Hibernate.BINARY.nullSafeGet(rs, names,
				session, owner);
		IoBuffer buffer = IoBuffer.wrap(bytes);
		try {
			dbdict = (DBDict) codec.decode(buffer);
		} catch (DecodeException e) {
			throw new HibernateException(e.getMessage(), e);
		}

		return dbdict;
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index,
			SessionImplementor session) throws HibernateException, SQLException {
		DBDict dbdict = (DBDict) value;
		IoBuffer buffer = IoBuffer.allocate(MAX_SIZE);
		buffer.setAutoExpand(true);
		try {
			codec.encode(buffer, dbdict);
		} catch (EncodeException e) {
			throw new HibernateException(e.getMessage(), e);
		}
		buffer.flip();
		byte[] bytes = new byte[buffer.limit()];
		buffer.get(bytes);
		Hibernate.BINARY.nullSafeSet(st, bytes, index, session);

	}
}
